#include "bsp_uart.h"
#include "string.h"
#include "bsp_print.h"



static uint8_t dma_rbuf[UART4_MAX];
static uint8_t dma_tbuf[UART4_MAX];
st_uart4 st_485;
/**
  * @brief  config dma for uart4
  * @param  none
  * @retval none
  */
void dma_configuration(void)
{
	dma_init_type dma_init_struct;
	
	/* enable dma1 clock */
	crm_periph_clock_enable(CRM_DMA1_PERIPH_CLOCK, TRUE);
	/* dma1 channel1 for uart4 tx configuration */
	dma_reset(DMA1_CHANNEL1);
	dma_default_para_init(&dma_init_struct);
	dma_init_struct.buffer_size = UART4_MAX;
	dma_init_struct.direction = DMA_DIR_MEMORY_TO_PERIPHERAL;
	dma_init_struct.memory_base_addr = (uint32_t)dma_tbuf;
	dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_BYTE;
	dma_init_struct.memory_inc_enable = TRUE;
	dma_init_struct.peripheral_base_addr = (uint32_t)&UART4->dt;
	dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_BYTE;
	dma_init_struct.peripheral_inc_enable = FALSE;
	dma_init_struct.priority = DMA_PRIORITY_MEDIUM;
	dma_init_struct.loop_mode_enable = FALSE;
	dma_init(DMA1_CHANNEL1, &dma_init_struct);
	
	/* enable transfer full data intterrupt */
	dma_interrupt_enable(DMA1_CHANNEL1, DMA_FDT_INT, TRUE);
	/* dma1 channel1 interrupt nvic init */
	nvic_irq_enable(DMA1_Channel1_IRQn, 0, 0);
	/* config flexible dma for usart2 tx */
	dma_flexible_config(DMA1, FLEX_CHANNEL1, DMA_FLEXIBLE_UART4_TX);
	
	/* dma1 channel2 for uart4 rx configuration */
	dma_reset(DMA1_CHANNEL2);
	dma_default_para_init(&dma_init_struct);
	dma_init_struct.buffer_size = UART4_MAX;
	dma_init_struct.direction = DMA_DIR_PERIPHERAL_TO_MEMORY;
	dma_init_struct.memory_base_addr = (uint32_t)dma_rbuf;
	dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_BYTE;
	dma_init_struct.memory_inc_enable = TRUE;
	dma_init_struct.peripheral_base_addr = (uint32_t)&UART4->dt;
	dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_BYTE;
	dma_init_struct.peripheral_inc_enable = FALSE;
	dma_init_struct.priority = DMA_PRIORITY_MEDIUM;
	dma_init_struct.loop_mode_enable = FALSE;
	dma_init(DMA1_CHANNEL2, &dma_init_struct);
	
	/* enable transfer full data intterrupt */
	dma_interrupt_enable(DMA1_CHANNEL2, DMA_FDT_INT, TRUE);
	
	/* dma1 channel2 interrupt nvic init */
	nvic_irq_enable(DMA1_Channel2_IRQn, 0, 0);
	
	/* config flexible dma for usart2 rx */
	dma_flexible_config(DMA1, FLEX_CHANNEL2, DMA_FLEXIBLE_UART4_RX);
	
	dma_channel_enable(DMA1_CHANNEL1, TRUE); /* uart4 tx begin dma transmitting */
	dma_channel_enable(DMA1_CHANNEL2, TRUE); /* uart4 rx begin dma receiving */
}

/**
  * @brief  initialize led function
  * @param  none
  * @retval none
  */
void at32_rs485_init(void)
{
	gpio_init_type gpio_init_struct;

	/* enable the usart2 and gpio clock */
	crm_periph_clock_enable(CRM_UART4_PERIPH_CLOCK, TRUE);
	crm_periph_clock_enable(CRM_GPIOC_PERIPH_CLOCK, TRUE);
	crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
	gpio_pin_remap_config(SWJTAG_MUX_010, TRUE);

	gpio_default_para_init(&gpio_init_struct);
	/* configure the 485 tx pin */
	gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
	gpio_init_struct.gpio_out_type  = GPIO_OUTPUT_PUSH_PULL;
	gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
	gpio_init_struct.gpio_pins = GPIO_PINS_10;
	gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
	gpio_init(GPIOC, &gpio_init_struct);

	/* configure the 485 rx pin */
	gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
	gpio_init_struct.gpio_out_type  = GPIO_OUTPUT_PUSH_PULL;
	gpio_init_struct.gpio_mode = GPIO_MODE_INPUT;
	gpio_init_struct.gpio_pins = GPIO_PINS_11;
	gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
	gpio_init(GPIOC, &gpio_init_struct);
	
	/* configure the 485 de pin */
	gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
	gpio_init_struct.gpio_out_type  = GPIO_OUTPUT_PUSH_PULL;
	gpio_init_struct.gpio_pins = GPIO_PINS_15;
	gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
	gpio_init_struct.gpio_pull = GPIO_PULL_DOWN;
	gpio_init(GPIOA, &gpio_init_struct);
	
	/* default the 485 rx mode */
	gpio_bits_reset(GPIOA, GPIO_PINS_15);
	/* configure uart4 param */
	usart_init(UART4, 115200, USART_DATA_8BITS, USART_STOP_1_BIT);
	usart_transmitter_enable(UART4, TRUE);
	usart_receiver_enable(UART4, TRUE);
	usart_interrupt_enable(UART4,USART_RDBF_INT, TRUE);
	usart_interrupt_enable(UART4,USART_IDLE_INT, TRUE);
	/* dma1 channel2 interrupt nvic init */
	nvic_irq_enable(UART4_IRQn, 1, 0);
	
	usart_dma_transmitter_enable(UART4, TRUE);
	usart_dma_receiver_enable(UART4, TRUE);
	usart_enable(UART4, TRUE);
	dma_configuration();
	st_485.status.bit.b_recving = 1;
}

/**
  * @brief  this function handles uart4 handler.
  * @param  none
  * @retval none
  */
void UART4_IRQHandler(void)
{
	uint8_t s_rx_cnt = 0;
	if(usart_flag_get(UART4, USART_IDLEF_FLAG) != RESET)
	{
		usart_flag_clear(UART4, USART_IDLEF_FLAG);
		dma_channel_enable(DMA1_CHANNEL2, FALSE);
		s_rx_cnt = UART4_MAX - dma_data_number_get(DMA1_CHANNEL2);
		if((s_rx_cnt > 0) && (s_rx_cnt <= UART4_MAX)){
			st_485.rx_cnt = s_rx_cnt;
			memcpy(st_485.rx_buf,dma_rbuf,s_rx_cnt);
			st_485.status.bit.b_recved = 1;
			st_485.status.bit.b_recving = 0;
			st_485.status.bit.b_sended = 0;
			st_485.status.bit.b_sending = 0;
		}
		
		dma_data_number_set(DMA1_CHANNEL2,UART4_MAX);
		dma_flexible_config(DMA1, FLEX_CHANNEL2, DMA_FLEXIBLE_UART4_RX);
		dma_channel_enable(DMA1_CHANNEL2,TRUE);
	}
}

/**
  * @brief  this function handles for dma1 ch1 uart4 tx.
  * @param  none
  * @retval none
  */
void DMA1_Channel1_IRQHandler(void)
{
	if(dma_flag_get(DMA1_FDT1_FLAG)){
		dma_flag_clear(DMA1_FDT1_FLAG);
		
		st_485.status.bit.b_recved = 0;
		st_485.status.bit.b_recving = 0;
		st_485.status.bit.b_sended = 1;
		st_485.status.bit.b_sending = 0;
		st_485.conversion_time = 5;
		dma_channel_enable(DMA1_CHANNEL1, FALSE);           
		usart_dma_transmitter_enable(UART4,FALSE);
		
	}
}

/**
  * @brief  this function handles for dma1 ch2 uart4 rx.
  * @param  none
  * @retval none
  */
void DMA1_Channel2_IRQHandler(void)
{
	if(dma_flag_get(DMA1_FDT2_FLAG)){
		dma_flag_clear(DMA1_FDT2_FLAG);
	}
}

/**
  *  @brief  rs485 send data
  *  @param  buf: pointer to the buffer that contain the data to be transferred.
  *  @param  cnt: size of buffer in bytes.
  *  @retval none
  */
void rs485_send_data(u8* buf, u8 cnt)
{
	gpio_bits_set(GPIOA, GPIO_PINS_15);
	
	DMA1_CHANNEL1->dtcnt=cnt;                          
	DMA1_CHANNEL1->maddr=(uint32_t)buf;                
	usart_dma_transmitter_enable(UART4,TRUE);        
	dma_channel_enable(DMA1_CHANNEL1, TRUE);            
	
	st_485.status.bit.b_recved = 0;
	st_485.status.bit.b_recving = 0;
	st_485.status.bit.b_sended = 0;
	st_485.status.bit.b_sending = 1;
}


